/**
 * File: AbstractWriter.java
 * Created by: mhaimel
 * Created on: 18 Aug 2009
 * CVS:  $Id: AbstractWriter.java,v 1.3 2009/10/09 15:14:58 mhaimel Exp $
 */
package uk.ac.ebi.curtain.util.io;

import java.io.Closeable;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

import uk.ac.ebi.velvet.model.Strand;

/**
 * @author mhaimel
 *
 */
public abstract class AbstractWriter<T> implements Closeable {
	protected static final char SEP_CHAR = '\t';
	protected final Object SYNC_OBJ = new Object();
	private final AtomicLong iCnt = new AtomicLong(0l);

	private final AtomicReference<PrintWriter> out = new AtomicReference<PrintWriter>(null);

	public AbstractWriter(PrintWriter out) {
		this.out.set(out);
	}
	
	public Long getCount(){
		return iCnt.get();
	}
	
	public void write(T bean){
		synchronized (SYNC_OBJ) {
			_doCountWrite(bean);
		}
	}
	
	public void write(Iterable<T> iter){
		synchronized (SYNC_OBJ) {
			_doCountWrite(iter);
		}
	}

	protected void printSep() {
		getWriter().print(SEP_CHAR);
	}
	
	protected void _write(String str){
		getWriter().print(str);
	}
	protected void _write(Strand strand){
		if(null == strand){
			getWriter().print('x');
		} else {
			getWriter().print(strand.getSymbol());
		}
	}
	protected void _write(char c){
		getWriter().print(c);
	}
	protected void writeColumn(String str){
		getWriter().print(str);
		printSep();
	}
	protected void writeColumn(char c){
		getWriter().print(c);
		printSep();
	}
	protected void writeColumn(Strand strand){
		_write(strand);
		printSep();
	}
	protected String wrap(int i){
		return Integer.valueOf(i).toString();
	}
	protected String wrap(byte i){
		return Byte.valueOf(i).toString();
	}
	protected String wrap(long i){
		return Long.valueOf(i).toString();
	}
	
	protected PrintWriter getWriter() {
		return out.get();
	}
	
	protected void _doCountWrite(Iterable<T> iter) {
		for(T t : iter){
			_doCountWrite(t);
		}
	}

	protected void _doCountWrite(T bean){
		iCnt.incrementAndGet();
		_doWrite(bean);
	}

	protected abstract void _doWrite(T bean);

	/**
	 * {@inheritDoc}
	 */
	public void close() throws IOException {
		synchronized (SYNC_OBJ) {
			out.getAndSet(null).close();
		}
	}
}
